package com.kgc.scd.service.impl;

import com.kgc.scd.bean.Order;
import com.kgc.scd.config.WechatPayConfig;
import com.kgc.scd.contant.WechatPayConstant;
import com.kgc.scd.mapper.OrderMapper;
import com.kgc.scd.service.WechatPayService;
import com.kgc.scd.util.HttpClient4Util;
import com.kgc.scd.util.WechatPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.TreeMap;

/**
 * Created On : 2022/5/31.
 * <p>
 * Author     : 98730
 * <p>
 * Description: 微信支付业务接口实现类
 */
@Slf4j
@Service
public class WechatPayServiceImpl implements WechatPayService {

    @Autowired
    private WechatPayConfig wechatPayConfig;

    @Autowired(required = false)
    private OrderMapper orderMapper;

    @Override
    public String wechatUnifiedOrderParamsXml(String body, int totalFee, String prodId,String orderId) throws Exception{

        // 微信官方接口集合参数的要求：设所有发送或者接收到的数据为集合M，将集合M内非空参数值的参数按照参数名ASCII码从小到大排序（字典序），参数名区分大小写，sign参数不参与签名
        // 定义微信官方统一下单的参数集合，要求：根据参数名字典序排序，可选的集合：TreeMap，自动根据key进行自然排序
        Map<String, String> paramsMap = new TreeMap<>();

        // 公众号id
        paramsMap.put("appid",wechatPayConfig.getAppId());

        // 商户号
        paramsMap.put("mch_id",wechatPayConfig.getMchId());

        // 设备号,PC网页或公众号内支付可以传"WEB"
        paramsMap.put("device_info","WEB");

        // 随机字符串,长度要求在32位以内。增加签名的安全性
        paramsMap.put("nonce_str", WechatPayUtil.generateNonceStrUseRandom());

        // 商品描述
        paramsMap.put("body", body);

        // 商品详情,商品详细描述，对于使用单品优惠的商户，该字段必须按照规范上传,商品信息的json字符串，从数据库查询的商品信息

        // 附加数据
        paramsMap.put("attach","KGC南京分部");

        // 商户订单号
        paramsMap.put("out_trade_no", orderId);

        // 标价金额，单位：分
        paramsMap.put("total_fee", String.valueOf(totalFee));

        // 终端IP
        paramsMap.put("spbill_create_ip", "127.0.0.1");

        // 通知地址，body 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。使用内网穿透
        paramsMap.put("notify_url", wechatPayConfig.getNotifyUri());

        // 交易类型，NATIVE- Native支付
        paramsMap.put("trade_type", WechatPayConstant.WECHAT_PAY_TRADE_TYPE_NATIVE);

        // 商品ID，trade_type=NATIVE时，此参数必传。
        paramsMap.put("product_id",prodId);

        // 生成前面，sign参数不参与前面，作为借口参数传递前面的结果
        // 一般情况下，都是将所有的签名参数确定后，最后进行签名处理，将签名后的sign集合
        paramsMap.put("sign",WechatPayUtil.generateSignature(paramsMap,wechatPayConfig.getMchKey()));

        return WechatPayUtil.generateParamsStrMapToXml(paramsMap);
    }

    @Override
    public Map<String, String> wechatPayUnifiedOrder(String unifiedOrderParamsXml) throws Exception {
        // 内部发http请求，到微信官方进行统一下预支付订单，必须使用post请求，同步返回一个下单结果字符串，xml格式
        String UnifiedOrderResultXml = HttpClient4Util.getResponse4PostByString(wechatPayConfig.getOrderUri(), unifiedOrderParamsXml, WechatPayConstant.WECHAT_PAY_ENCODING_UTF8);

        // 统一下预支付订单，转换为map集合，返回
        return WechatPayUtil.generateResultMapUseXmlToMap(UnifiedOrderResultXml);
    }

    @Override
    public String wechatPayNotifyResultResolve(String wxPayNotifyResultXml) throws Exception{

        // 将微信官方异步回调结果，转换为map集合
        Map<String,String> wxPayNotifyResultMap = WechatPayUtil.generateResultMapUseXmlToMap(wxPayNotifyResultXml);

        // 解析成功结果
        if (WechatPayConstant.WECHAT_PAY_SUCCESS.equals(wxPayNotifyResultMap.get("return_code"))){
            // 进行签名校验，商户系统对于支付结果通知的内容一定要做签名验证，并校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄露导致出现“假通知“，造成金额损失
            if (WechatPayUtil.isSignatureValid(wxPayNotifyResultMap, wechatPayConfig.getMchKey())){
                // 签名成功，响应是可信且正确的
                // TODO 业务处理，比如：修改订单状态，会用户加积分等等
                Order order = orderMapper.selectById(wxPayNotifyResultMap.get("out_trade_no"));
                order.setOrderId(wxPayNotifyResultMap.get("out_trade_no"));
                order.setOrderState(1);
                orderMapper.updateById(order);
                // 响应微信官方成功

                return WechatPayConstant.WECHAT_PAY_NOTIFY_RESULT_RESPONSE_SUCCESS;

            }
        }
        // 响应微信官方失败
        return WechatPayConstant.WECHAT_PAY_NOTIFY_RESULT_RESPONSE_FAIL;

    }


}
